package eval

import (
	"showen/lex"
	"showen/obj"
	"showen/parse"
	"testing"
)

func TestBegin(t *testing.T) {
	tests := []struct {
		input    string
		expected string
	}{
		{
			"(begin 1)",
			"1",
		},
		{
			"(begin 1 2 3)",
			"3",
		},
		{
			"(begin (define x 10) x)",
			"10",
		},
		{
			"(begin (define x 10) (define y 20) (+ x y))",
			"30",
		},
		{
			"(begin)",
			"",
		},
	}

	env := obj.NewEnvironment()
	RegisterBuiltinProcedures(env)

	for _, tt := range tests {
		lexer := lex.NewLexer(tt.input)
		tokens := lexer.ReadTokens()
		parser := parse.NewParser(tokens)
		expr, err := parser.ParseExpression()
		if err != nil {
			t.Fatalf("parser.ParseExpression() error = %v", err)
		}

		result, err := EvalExpression(expr, env)
		if err != nil {
			t.Fatalf("Eval() error = %v", err)
		}

		expected := tt.expected
		if expected == "" {
			// Empty begin should return null
			expected = (&obj.NullObject{}).Inspect()
		}

		if result.Inspect() != expected {
			t.Errorf("Eval() = %v, want %v", result.Inspect(), expected)
		}
	}
}
